using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using SCSEngine.Utils.Entities.Process;
using SCSEngine.Utils.Entities.Component.Accelerometer;

namespace SCSEngine.Utils.Entities.Process.Accelerometer
{
    public class AccelerometerManager : BaseGameProcessManager
    {
        private Microsoft.Devices.Sensors.Accelerometer accelerometer;
        private IAccelerometComponent accelComponent;

        private bool needUpdateAcceleromet = true;

        public float SmoothCoefficient { get; set; }

        public IAccelerometComponent AccelerometerComponent
        {
            get { return accelComponent; }
        }

        public AccelerometerManager()
        {
            this.accelComponent = new AccelerometComponent();

            this.accelerometer = new Microsoft.Devices.Sensors.Accelerometer();
            this.accelerometer.CurrentValueChanged += this.AccelValueChanged;

            this.SmoothCoefficient = 0.15f;
        }

        private void AccelValueChanged(object sender, Microsoft.Devices.Sensors.SensorReadingEventArgs<Microsoft.Devices.Sensors.AccelerometerReading> e)
        {
            if (this.needUpdateAcceleromet)
            {
                this.accelComponent.Value = this.LowPassFilter(e.SensorReading.Acceleration, this.accelComponent.Value, this.SmoothCoefficient);
                this.needUpdateAcceleromet = false;

                this.DispatchAcceleromet(e.SensorReading.Timestamp);
            }
        }

        private Vector3 LowPassFilter(Vector3 raw, Vector3 old, float coeff)
        {
            return old + coeff * (raw - old);
        }

        private void DispatchAcceleromet(DateTimeOffset timeStamp)
        {
            foreach (IAccelerometProcess accelProcess in this.Processes)
            {
                accelProcess.AccelerometerChanged(this.accelComponent, timeStamp);
            }
        }

        protected override bool IsValidProcess(object process)
        {
            return process is IAccelerometProcess;
        }

        public override void Run(Game game, GameTime gameTime)
        {
            // do nothing, this PM is auto dispatch
            this.needUpdateAcceleromet = true;
        }

        public override bool IsDrawProcess
        {
            get { return false; }
        }

        public override Type ProcessType
        {
            get { return typeof(IAccelerometProcess); }
        }

        public override void Start(Game game)
        {
            this.accelerometer.Start();
            base.Start(game);
        }

        public override void Pause(Game game)
        {
            this.accelerometer.Stop();
            base.Pause(game);
        }

        public override void Stop(Game game)
        {
            this.accelerometer.Stop();
            base.Stop(game);
        }
    }
}